import serial
import threading
import time
import platform
from app.utils.config_loader import app_config
from app.utils.logger import ETCLogger

# 初始化日志记录器
logger = ETCLogger()

class SerialManager:
    def __init__(self):
        self.serial_ports = {}  # 存储打开的串口对象
        self.reconnect_interval = 5  # 重连间隔时间（秒）
        self.reconnect_thread = None
        self.running = False
        self.lock = threading.Lock()  # 线程锁

    def is_port_available(self, port):
        """
        检测串口是否可用
        :param port: 串口名称（如 "COM1" 或 "/dev/ttyUSB0"）
        :return: 是否可用
        """
        try:
            ser = serial.Serial(port)
            ser.close()
            return True
        except serial.SerialException:
            return False

    def open_port(self, port, baudrate):
        """
        打开串口
        :param port: 串口名称
        :param baudrate: 波特率
        :return: 是否成功打开
        """
        if port in self.serial_ports:
            return True  # 串口已打开

        try:
            ser = serial.Serial(port, baudrate)
            self.serial_ports[port] = ser
            logger.device_log(f"Successfully opened serial port: {port}, baudrate: {baudrate}", device_name=port)
            return True
        except Exception as e:
            logger.device_log(f"Failed to open serial port {port}: {e}", device_name=port)
            return False

    def send_data(self, port, data):
        """
        向串口发送数据
        :param port: 串口名称
        :param data: 要发送的数据
        :return: 是否成功发送
        """
        if port not in self.serial_ports:
            return False

        try:
            with self.lock:  # 加锁，确保线程安全
                self.serial_ports[port].write(data)
                logger.device_log(f">>> Sent: {data}", device_name=port)
                return True
        except Exception as e:
            logger.device_log(f"Failed to send data to serial port {port}: {e}", device_name=port)
            return False

    def read_data(self, port, timeout=1):
        """
        从串口读取数据
        :param port: 串口名称
        :param timeout: 超时时间（秒）
        :return: 读取到的数据
        """
        if port not in self.serial_ports:
            return None

        try:
            with self.lock:  # 加锁，确保线程安全
                self.serial_ports[port].timeout = timeout
                data = self.serial_ports[port].read_all()
                logger.device_log(f"<<< Received: {data}", device_name=port)
                return data
        except Exception as e:
            logger.device_log(f"Failed to read data from serial port {port}: {e}", device_name=port)
            return None

    def close_port(self, port):
        """
        关闭串口
        :param port: 串口名称
        :return: 是否成功关闭
        """
        if port in self.serial_ports:
            self.serial_ports[port].close()
            del self.serial_ports[port]
            logger.device_log(f"Closed serial port: {port}", device_name=port)
            return True
        return False

    def close_all_ports(self):
        """关闭所有串口"""
        for port in list(self.serial_ports.keys()):
            self.close_port(port)

    def start_reconnect_thread(self):
        """
        启动断线重连线程
        """
        self.running = True
        self.reconnect_thread = threading.Thread(target=self._reconnect_ports)
        self.reconnect_thread.daemon = True  # 设置为守护线程
        self.reconnect_thread.start()

    def stop_reconnect_thread(self):
        """
        停止断线重连线程
        """
        self.running = False
        if self.reconnect_thread:
            self.reconnect_thread.join()

    def _reconnect_ports(self):
        """
        断线重连逻辑
        """
        while self.running:
            for port in list(self.serial_ports.keys()):
                if not self.serial_ports[port].is_open:
                    logger.device_log(f"Serial port {port} disconnected, attempting to reconnect...", device_name=port)
                    self.close_port(port)
                    if self.is_port_available(port):
                        baudrate = self._get_baudrate_for_port(port)
                        self.open_port(port, baudrate)
            time.sleep(self.reconnect_interval)

    def _get_baudrate_for_port(self, port):
        """
        获取串口的波特率
        :param port: 串口名称
        :return: 波特率
        """
        os_type = "windows" if platform.system() == "Windows" else "linux"
        ports = app_config.get(f"serial_ports.{os_type}")
        baud_rates = app_config.get("baud_rates")

        for device, p in ports.items():
            if p == port:
                return baud_rates.get(device)
        return 9600  # 默认波特率